package cvo.chess.client.ui.chessboard;

import java.util.ArrayList;
import java.util.List;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOutHandler;
import com.google.gwt.event.dom.client.MouseOverEvent;
import com.google.gwt.event.dom.client.MouseOverHandler;
import com.google.gwt.event.dom.client.MouseUpEvent;
import com.google.gwt.event.dom.client.MouseUpHandler;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.Widget;

import cvo.chess.client.entities.IGameFacade;
import cvo.chess.client.entities.chessboard.ChessboardCoordinate;
import cvo.chess.client.entities.game.IChessboard;
import cvo.chess.client.entities.game.IPiece;

public class ChessboardWidget extends Composite{

	private static ChessboardWidgetUiBinder uiBinder = GWT
			.create(ChessboardWidgetUiBinder.class);

	interface ChessboardWidgetUiBinder extends UiBinder<Widget, ChessboardWidget> {
	}
	
	List<TileWidget> tiles = new ArrayList<TileWidget>();	
	IGameFacade gf;
	
	@UiField 
	FlexTable grid;
	
	//Keep a reference to the last selected tile.
	TileWidget currentSelectedTile;
	
	public ChessboardWidget(IGameFacade gf) {
		initWidget(uiBinder.createAndBindUi(this));
		this.gf = gf;
		init();
	}

	/**
	 *  Create Tiles and place them on the board
	 */
	private void init()
	{
		IChessboard board = gf.getBoard();
		char lastChar =  (char)('A' + board.getWidth()-1);
		for(Character x = 'A' ; x <= lastChar ; x++)
		{
			for(int y = 1; y <= board.getHeight(); y++)
			{
				String a1Notation = x.toString().concat(String.valueOf(y));
				TileWidget tw = new TileWidget(gf, a1Notation);
				this.tiles.add(tw);			
				//Here we place the tiles on the board. Remember It goes bottom-up from A to ... (probably: H) 
				this.grid.setWidget(board.getHeight() - (y- 1),(x - 'A'), tw);
				
				addHandlers(tw);
			}			
		}
	}
	
	private void addHandlers(final TileWidget tw) {
		//Add an mouse over event handler
		tw.addMouseOverHandler(new MouseOverHandler() {	
			@Override
			public void onMouseOver(MouseOverEvent event) {
				tw.lightUp(true);
			}
		});
		
		//Add an mouse out event handler
		tw.addMouseOutHandler(new MouseOutHandler() {
			@Override
			public void onMouseOut(MouseOutEvent event) {
				tw.lightUp(false);
			}
		});
		
		//Add an mouse up event handler
		tw.addMouseUpHandler(new MouseUpHandler() {
			@Override
			public void onMouseUp(MouseUpEvent event) {
				clearPossibleMovePosition();
				if(currentSelectedTile!=null){					
					//De-border the previously selected tile
					currentSelectedTile.hardBorder(false);					
				}
				//Checks whether the previously sected tile is the same
				if(currentSelectedTile==tw) { //If it is the same, just unselect the tiles
					tw.hardBorder(false);
					clearPossibleMovePosition();
				} else {				
					currentSelectedTile = tw;
					tw.hardBorder(true);
					lightupPossibleMovePositions(tw);
				}
			}
		});
		
	}

	public void update(){
		for(TileWidget tw : tiles){
			tw.update();
		}
	}

	@UiHandler("updateButton")
	void onUpdateButtonClick(ClickEvent e) {
		this.update();
	}
	
	public void lightupPossibleMovePositions(TileWidget currentSelectedTile){
		IPiece piece = gf.getPieceAt(currentSelectedTile.getA1Notation());


		if(piece!=null){
			List<ChessboardCoordinate> possibleMoves;
			try {
				possibleMoves = piece.getPossibleMoves();
				
				for (ChessboardCoordinate chessboardCoordinate : possibleMoves) {
				
					TileWidget tile = getTileWidgetAt(chessboardCoordinate.getA1Notation());
		
					tile.isPossibleMovePosition(true);
				} 
			} catch (Exception e) {
				Window.alert("error Catch at possible moves");
				e.printStackTrace();
			}
		}
	}
	
	private TileWidget getTileWidgetAt(String A1Notation){
		for (TileWidget tile : tiles) {
			if(tile.getA1Notation().equals(A1Notation)){
				return tile;
			}
		}
		return null;
		
		
	}
	
	public void clearPossibleMovePosition(){
		for (TileWidget tw : this.tiles) {
			tw.isPossibleMovePosition(false);
		}
	}
}
